打包 python 程式是個大坑,現在沒有一個 python 打包器能完美打包所有 python 程式,尤其是機器學習函式庫。
我覺得難以打包的其中一個原因是因為 python 的特性...
動態語言,經常使用其他語言的函式庫,以及執行期間 import。
總之,pyinstaller 抓不到一些執行時需要的 dll,那麼來找吧。
我們可以根據這篇的解法,獲得 mkl_ 的 dll 位置,並加入到打包程式中。
https://stackoverflow.com/questions/35478526/pyinstaller-numpy-intel-mkl-fatal-error-cannot-load-mkl-intel-thread-dll
但兩邊的環境不同,他 的mkl_ dll 放在 /Lib/site-packages/numpy/core,而我的在
(以下的 spec 檔是 pyinstaller 在第一次打包時建立的設定檔,雖然附檔名是.spec 但實際上是當 python 執行的。)
打開 a01_flask_server.spec 並修改。
# a01_flask_server.spec
# -*- mode: python ; coding: utf-8 -*-
block_cipher = None
from PyInstaller import log as logging
from PyInstaller import compat
from os import listdir
mkldir = compat.base_prefix + "\\Library\\bin"
logger = logging.getLogger(__name__)
logger.info("MKL installed as part of numpy, importing that!")
binaries = [(mkldir + "\\" + mkl, '.') for mkl in listdir(mkldir) if mkl.startswith('mkl_')]
a = Analysis(['a01_flask_server.py'],
pathex=['D:\\vscode\\ithelp'],
binaries=binaries,
datas=[],
hiddenimports=[],
hookspath=[],
runtime_hooks=[],
excludes=[],
win_no_prefer_redirects=False,
win_private_assemblies=False,
cipher=block_cipher,
noarchive=False)
...
Analysis 中的 binaries 會在打包時將指定的檔案(二進位檔)放入資料夾,而在這裡我們就是要將缺少的 dll 放進去。
他的參數格式是 [("來源檔案或資料夾路徑", "目標資料夾夾路徑"), ("另一個來源", "另一個目標")...]
重新打包後讓我們再試著執行一次...
工作一樣,在你的 python 安裝路中找到並加進去。
binaries.append((compat.base_prefix +
"\Lib\site-packages\tensorflow\lite\experimental\microfrontend\python\ops",
"tensorflow\lite\experimental\microfrontend\python\ops"))
下一個
這次是函式庫不是檔案,所以要加的是這裡
hiddenimports=["keras.api"]
下一個
hiddenimports=["keras.api", "keras.api._v2"]
下一個...我還以為我需要把 keras 所有子模塊都寫進去。
這次是我程式的問題,它找不到要讀取的模型。
預設情況如果讀取檔案沒寫路徑,會尋找執行時時的當下路徑(如果使用捷徑開啟就會是捷徑的路徑),
這裡要把他改成相對於程式的路徑。
並且在打包時自動包進去。
# a06_mnist_api.py
import os
saved_model_path = os.path.dirname(__file__) + "\\mnist" + "\\mnist"
# a00_flask_server.spec
a = Analysis(['a01_flask_server.py'],
pathex=['D:\\vscode\\ithelp'],
binaries=binaries,
datas=[("mnist", "mnist")],
hiddenimports=["keras.api", "keras.api._v2"],
hookspath=[],
...
這樣應就好...了?
我想得太美了。
剩下的明天繼續...